
package com.lzb.browser.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Handler;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.ColorRes;
import androidx.annotation.Nullable;

import com.lzb.browser.R;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class PatternLockView extends View {

    public static final String TAG = "PatternLockView";

    private Context context;

    /**
     * 圆圈描边画笔
     */
    private Paint mPaint;
    /**
     * 连接线画笔
     */
    private Paint linePaint;
    /**
     * 文字画笔
     */
    private TextPaint textPaint;
    /**
     * 实心圆画笔
     */
    private Paint circlePaint;

    /**
     * 圆 半径
     */
    private float radius = 70;
    /**
     * 判定半径（用于触摸检测，比显示半径大一些）
     */
    private float hitRadius = 90;
    /**
     * 圆圈 选中颜色
     */
    private int selectedColor;
    /**
     * 圆圈填充颜色
     */
    private int color;
    /**
     * 圆圈描边颜色
     */
    private int strokeColor;
    /**
     * 连接线颜色
     */
    private int lineColor;
    /**
     * 圆圈描边宽度
     */
    private float strokeWidth = 2;
    /**
     * 连接线粗细
     */
    private float lineWidth = 2;
    /**
     * 提示信息
     */
    private String tips;
    private String defaultTips;
    /**
     * 文字颜色
     */
    private int textColor;
    /**
     * 文本大小
     */
    private float textSize;
    private List<Integer> values;
    private LinkedList<CircleView> circleViews;
    private LinkedList<PointF> lines;
    /**
     * 手指实时位置
     */
    private float x, y;

    /**
     * 起始坐标
     */
    private float startX, startY;


    public PatternLockView(Context context) {
        super(context);
        this.context = context;
        init(null);
    }

    public PatternLockView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init(attrs);
    }

    public PatternLockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        values = new LinkedList<>();
        circleViews = new LinkedList<>();
        lines = new LinkedList<>();

        if (attrs == null) {
            selectedColor = R.color.lock_view_selected_color;
            color = R.color.lock_view_default_color;
            strokeColor = R.color.lock_view_stroke_color;
            lineColor = R.color.lock_view_line_color;
            textColor = R.color.lock_view_text_color;
        } else {
            TypedArray typedArray = context.obtainStyledAttributes(attrs,
                    R.styleable.PatternLockView);

            radius = typedArray.getDimension(R.styleable.PatternLockView_radius, 20);
            selectedColor = typedArray.getColor(R.styleable.PatternLockView_selectedColor, getColor(R.color.lock_view_selected_color));
            color = typedArray.getColor(R.styleable.PatternLockView_color, getColor(R.color.lock_view_default_color));
            strokeColor = typedArray.getColor(R.styleable.PatternLockView_strokeColor, getColor(R.color.lock_view_stroke_color));
            strokeWidth = typedArray.getDimension(R.styleable.PatternLockView_strokeWidth, 2);
            lineColor = typedArray.getColor(R.styleable.PatternLockView_lineColor, getColor(R.color.lock_view_line_color));
            lineWidth = typedArray.getDimension(R.styleable.PatternLockView_lineWidth, 10);
            
            // 设置判定半径为显示半径的1.3倍，方便拖动操作
            hitRadius = radius * 1.3f;
            tips = typedArray.getString(R.styleable.PatternLockView_tips);
            defaultTips = tips;
            textColor = typedArray.getColor(R.styleable.PatternLockView_textColor, getColor(R.color.lock_view_text_color));
            textSize = typedArray.getDimension(R.styleable.PatternLockView_textSize, 20f);
            typedArray.recycle();
        }


        mPaint = new Paint();
        // 设置画笔为抗锯齿
        mPaint.setAntiAlias(true);
        // 设置描边颜色
        mPaint.setColor(strokeColor);
        /**
         * 画笔样式分三种： 1.Paint.Style.STROKE：描边 2.Paint.Style.FILL_AND_STROKE：描边并填充
         * 3.Paint.Style.FILL：填充
         */
        mPaint.setStyle(Paint.Style.STROKE);
        /**
         * 设置描边的粗细，单位：像素px 注意：当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素
         */
        mPaint.setStrokeWidth(strokeWidth);
        linePaint = new Paint();
        linePaint.setAntiAlias(true);
        linePaint.setColor(lineColor);
        linePaint.setStrokeWidth(lineWidth);
        linePaint.setStyle(Paint.Style.FILL);

        textPaint = new TextPaint();
        textPaint.setAntiAlias(true);
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize);
        //textPaint.setTextAlign(Paint.Align.CENTER);

        circlePaint = new Paint();
        circlePaint.setAntiAlias(true);
        circlePaint.setColor(color);
        circlePaint.setStyle(Paint.Style.FILL);

        for (int i = 1; i <= 9; i++) {
            circleViews.add(new CircleView(i));
        }

        initCircle();
    }


    private void initCircle() {
        int w = getWidth();
        if (w == 0)
            return;
        // 初始化起始坐标
        startX = w / 2 - 20;
    }

    private Handler handler = new Handler();


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 初始化Y坐标
        startY = 90;

        //绘制提示信息
        if (!TextUtils.isEmpty(tips)) {
            startY += 50;

            float stringWidth = textPaint.measureText(tips);
            float x = getWidth() / 2 - stringWidth / 2;

            canvas.drawText(tips, x, startY, textPaint);
        }

        int index = 0;
        // 圆圈距离提示信息70
        startY += 70;
        
        // 计算可用宽度和高度
        int availableWidth = getWidth() - getPaddingLeft() - getPaddingRight();
        int availableHeight = getHeight() - (int)startY - getPaddingBottom();
        
        // 计算圆之间的间距，使圆均分整个区域
        float horizontalSpacing = (availableWidth - radius * 2 * 3) / 4; // 4个间隔区域（左、中、右）
        float verticalSpacing = (availableHeight - radius * 2 * 3) / 4; // 4个间隔区域（上、中、下）
        
        // 确保间距不小于0
        horizontalSpacing = Math.max(horizontalSpacing, radius * 0.5f);
        verticalSpacing = Math.max(verticalSpacing, radius * 0.5f);
        
        // 计算起始位置，使圆居中
        float startX = getPaddingLeft() + horizontalSpacing;
        float currentY = startY + verticalSpacing;
        
        // 第一步：先绘制连接线（显示在圆的下方）
        // 连接线从圆的中心到圆的中心
        for (int i = 1; i < lines.size(); i++) {
            PointF firstNode = lines.get(i - 1);
            PointF secondNode = lines.get(i);
            
            // 直接从圆心到圆心
            canvas.drawLine(firstNode.x, firstNode.y, secondNode.x, secondNode.y, linePaint);
        }
        
        // 绘制手指移动的预览线（始终显示）
        if (lines.size() > 0) {
            PointF last = lines.getLast();
            
            // 新的线从圆的中心出发
            canvas.drawLine(last.x, last.y, x, y, linePaint);
        }

        // 第二步：再绘制所有圆（连接线显示在圆的下方）
        for (int i = 1; i <= 3; i++) {
            float currentX = startX;
            for (int j = 1; j <= 3; j++) {
                CircleView item = circleViews.get(index);
                item.updateBounds(currentX, currentY);
                item.drawCircle(canvas);
                index++;
                currentX += radius * 2 + horizontalSpacing;
            }
            currentY += radius * 2 + verticalSpacing;
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //按下
                Log.e(TAG, "onTouchEvent: 按下");
                tips = defaultTips;
                this.invalidate();
                return true;
            case MotionEvent.ACTION_UP:
                //抬起
                //Log.e(TAG, "onTouchEvent: 抬起" );
                if (values.size() == 0)
                    return false;

                if (patternLockViewListener != null) {
                    int[] arr = new int[values.size()];
                    for (int i = 0; i < values.size(); i++) {
                        arr[i] = values.get(i);
                    }
                    patternLockViewListener.onLockEnd(arr);
                }
                // 不再自动清除图案，由用户决定是否清除

                return true;
            case MotionEvent.ACTION_MOVE:
                //移动
                x = event.getX();
                y = event.getY();
                //Log.e(TAG, "onTouchEvent: 移动" );
                for (CircleView item : circleViews) {
                    if (!item.isSelected) {
                        // 计算手指到圆心的距离
                        float centerX = item.bounds.left + radius;
                        float centerY = item.bounds.top + radius;
                        float distance = (float) Math.sqrt((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY));
                        
                        // 当手指进入圆的范围（到达判定边界）即可连接
                        if (distance <= hitRadius) {
                            // 添加中间点（不可跳过）
                            addIntermediatePoints(item.value);
                            
                            item.isSelected = true;
                            lines.add(new PointF(centerX, centerY));
                            values.add(item.value);
                            break;
                        }
                    }
                }
                this.invalidate();
                return true;
        }
        return super.onTouchEvent(event);
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        initCircle();
        this.invalidate();
    }


    /**
     * 添加中间点（不可跳过功能）
     * 当从一点到另一点时，自动添加中间的点
     */
    private void addIntermediatePoints(int targetValue) {
        if (values.size() == 0) {
            return;
        }
        
        int lastValue = values.get(values.size() - 1);
        if (lastValue == targetValue) {
            return;
        }
        
        // 获取需要添加的中间点
        List<Integer> intermediatePoints = getIntermediatePoints(lastValue, targetValue);
        
        // 添加中间点
        for (int point : intermediatePoints) {
            if (!values.contains(point)) {
                CircleView intermediateCircle = getCircleViewByValue(point);
                if (intermediateCircle != null && !intermediateCircle.isSelected) {
                    intermediateCircle.isSelected = true;
                    lines.add(new PointF(intermediateCircle.bounds.left + radius, intermediateCircle.bounds.top + radius));
                    values.add(point);
                }
            }
        }
    }
    
    /**
     * 获取两个点之间的中间点
     */
    private List<Integer> getIntermediatePoints(int start, int end) {
        List<Integer> result = new ArrayList<>();
        
        // 水平线：1-2-3，4-5-6，7-8-9
        if ((start == 1 && end == 3) || (start == 3 && end == 1)) {
            result.add(2);
        } else if ((start == 4 && end == 6) || (start == 6 && end == 4)) {
            result.add(5);
        } else if ((start == 7 && end == 9) || (start == 9 && end == 7)) {
            result.add(8);
        }
        // 垂直线：1-4-7，2-5-8，3-6-9
        else if ((start == 1 && end == 7) || (start == 7 && end == 1)) {
            result.add(4);
        } else if ((start == 2 && end == 8) || (start == 8 && end == 2)) {
            result.add(5);
        } else if ((start == 3 && end == 9) || (start == 9 && end == 3)) {
            result.add(6);
        }
        // 对角线：1-5-9，3-5-7
        else if ((start == 1 && end == 9) || (start == 9 && end == 1)) {
            result.add(5);
        } else if ((start == 3 && end == 7) || (start == 7 && end == 3)) {
            result.add(5);
        }
        
        return result;
    }
    
    /**
      * 根据值获取对应的CircleView
      */
     private CircleView getCircleViewByValue(int value) {
         for (CircleView circle : circleViews) {
             if (circle.value == value) {
                 return circle;
             }
         }
         return null;
     }
     
     private int getColor(@ColorRes int colorId) {
         return context.getResources().getColor(colorId);
     }

    /**
     * 设置圆圈描边颜色
     */
    public void setStrokeColor(int strokeColor) {
        this.strokeColor = strokeColor;
        mPaint.setColor(strokeColor);
        this.invalidate();
    }

    /**
     * 设置实心圆填充颜色
     */
    public void setColor(int color) {
        this.color = color;
        circlePaint.setColor(color);
        this.invalidate();
    }

    /**
     * 设置圆圈描边宽度
     */
    public void setStrokeWidth(float strokeWidth) {
        this.strokeWidth = strokeWidth;
        mPaint.setStrokeWidth(strokeWidth);
        this.invalidate();
    }

    /**
     * 设置连接线粗细
     */
    public void setLineWidth(float lineWidth) {
        this.lineWidth = lineWidth;
        linePaint.setStrokeWidth(lineWidth);
        invalidate();
    }

    /**
     * 设置提示信息
     *
     * @param tips
     */
    public void setTips(String tips) {
        this.tips = tips;
        this.invalidate();
    }

    /**
     * 清除图案
     * 清除所有选中的圆和连接线
     */
    public void clearPattern() {
        for (CircleView item : circleViews) {
            item.isSelected = false;
        }
        values.clear();
        lines.clear();
        this.invalidate();
    }

    private PatternLockViewListener patternLockViewListener;

    public void setPatternLockViewListener(PatternLockViewListener patternLockViewListener) {
        this.patternLockViewListener = patternLockViewListener;
    }


    class CircleView {

        CircleView(int value) {
            bounds = new RectF();
            this.value = value;
        }

        int value;
        RectF bounds;
        boolean isSelected;

        void updateBounds(float x, float y) {
            bounds.top = y;
            bounds.left = x;
            bounds.bottom = y + radius * 2;
            bounds.right = x + radius * 2;
        }

        /**
         * 画圆
         *
         * @param canvas
         */
        void drawCircle(Canvas canvas) {
            // 绘制实心圆
            if (isSelected) {
                circlePaint.setColor(selectedColor);
            } else {
                circlePaint.setColor(color);
            }
            canvas.drawCircle(bounds.left + radius, bounds.top + radius, radius, circlePaint);

            // 绘制边框
            if (strokeWidth > 0) {
                if (isSelected) {
                    mPaint.setColor(selectedColor);
                } else {
                    mPaint.setColor(strokeColor);
                }
                canvas.drawCircle(bounds.left + radius, bounds.top + radius, radius, mPaint);
            }
        }

    }

    public interface PatternLockViewListener {
        void onLockEnd(int[] values);
    }

}
